package CSV;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

public class AssociateRules {

	
	final static String csvpath = "INTEGRATED-DATASET.csv";
	HashSet<String> wholeset;
	HashMap<Integer, HashSet<String>> transactionset;
	HashMap<ArrayList<String>, Integer> LHSRHS;
	HashMap<Rules, Double> answer;
	double minsup;
	double minconf;	
	
	public AssociateRules(double minsup, double minconf){
		this.wholeset = new HashSet<String>();
		this.transactionset = new HashMap<Integer, HashSet<String>>();
		this.LHSRHS = new HashMap<ArrayList<String>, Integer>();
		this.answer = new HashMap<Rules, Double>();
		this.minconf = minconf;
		this.minsup = minsup;
	}
	
	@SuppressWarnings("unchecked")
	public void printAnswer() throws IOException{
		FileWriter fw = null;
		fw = new FileWriter("output.txt");
		BufferedWriter bf = new BufferedWriter(fw);
		
		// sort the LHSRHS 
		ArrayList myArrayLargeItem = new ArrayList(this.LHSRHS.entrySet());
		Collections.sort(myArrayLargeItem, new MyComparatorInteger());
		
		// print the large item set
		double sup = this.minsup * 100.0;
		bf.write("==Large itemsets (min_sup="+sup+"%)\n");
		Iterator<Map.Entry<ArrayList<String>, Integer>> iter = myArrayLargeItem.iterator();
		while(iter.hasNext()){
			Map.Entry<ArrayList<String>, Integer> me = iter.next();
			float lisup = (float) (100.0*me.getValue()/this.transactionset.size());
			bf.write(me.getKey().toString()+", "+lisup+"%\n");
		}
		
		
		bf.write("\n");
		
		// sort the association rules
		ArrayList hcrules = new ArrayList(this.answer.entrySet());
		Collections.sort(hcrules, new MyComparatorDouble());
		
		// print the association rules
		double conf = (this.minconf * 100.0);
		bf.write("==High-confidence association rules (min_conf=" + conf + "%)\n");
		Iterator<Map.Entry<Rules, Double>> ruleiter = hcrules.iterator();
		while(ruleiter.hasNext()){
			Map.Entry<Rules, Double> me = (Map.Entry<Rules, Double>) ruleiter.next();
			Rules rule = me.getKey();
			double liconf = me.getValue() * 100;
			ArrayList<String> leftandright = findLHSRHS(rule);
			float lisup = (float) (100.0 * this.LHSRHS.get(leftandright)/this.transactionset.size());
			bf.write(rule.getLHS().toString());
			bf.write(" => ");
			bf.write(rule.getRHS().toString());
			bf.write("(Conf: "+liconf+"%, Supp: "+lisup+"%)\n");
		}
		bf.close();
	}
	
	public ArrayList<String> findLHSRHS(Rules rule){
		ArrayList<String> answer = new ArrayList<String>();
		answer.addAll(rule.getLHS());
		answer.addAll(rule.getRHS());
		Collections.sort(answer);
		return answer;
	}
	
	public static void main(String[] argv) {
		
		double minsup = 0.1;
		double minconf = 0.6;
		AssociateRules ar = new AssociateRules(minsup, minconf);
		FileReader read;
		BufferedReader br;
	
		// change the read in part
		//String path = "input";
		String path= csvpath;
		//new ProcessRawData(csvpath, path);
		int count = 0;
		String str = "";
		try {
			read = new FileReader(path);
			br = new BufferedReader(read);
			while ((str = br.readLine()) != null) {
				count ++;
				String[] attrs = str.split(",");
				HashSet<String> temphs = new HashSet<String>();
				for(int i = 0; i < attrs.length; i++){
					ar.wholeset.add(attrs[i]);
					temphs.add(attrs[i]);
				}
				ar.transactionset.put(count, temphs);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		// end read in part
		
		Apriori ap = new Apriori(ar.wholeset, minsup);
		ap.SetTran(ar.transactionset);
		ar.LHSRHS = ap.AprioriAlgo();
		RuleFinder rf = new RuleFinder(ar.LHSRHS,minconf);
		ar.answer = rf.findRules();

		try {
			ar.printAnswer();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}
